package net.jeeshop.services.manage.task.impl;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import net.jeeshop.core.ServersManager;
import net.jeeshop.core.common.dao.page.PagerModel;
import net.jeeshop.services.manage.task.bean.ProxyJob;
import net.jeeshop.services.manage.task.TaskService;
import net.jeeshop.services.manage.task.bean.Task;
import net.jeeshop.services.manage.task.dao.TaskDao;
import org.apache.commons.lang.StringUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.JobDetailImpl;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;


@Service("taskServiceManage")
public class TaskServiceImpl extends ServersManager<Task, TaskDao> implements TaskService, ApplicationContextAware {
    @Resource(name = "taskDaoManage")
    @Override
    public void setDao(TaskDao taskDao) {
        this.dao = taskDao;
    }
	@Autowired
	SchedulerFactoryBean schedulerFactoryBean;
	
	// 任务列表
	Map<String, Task> taskList = new LinkedHashMap<String, Task>();
	// 应用容器
	private ApplicationContext appcontext;


    @Override
    public int insert(Task task) {
        int id =super.insert(task);
        task.setId(id+"");
        try{
            addTask(task);
        }catch (Exception e) {
            e.printStackTrace();
        }
        return id;
    }

    @Override
    public int deletes(String[] ids) {
        if (ids == null || ids.length == 0) {
            throw new NullPointerException("id不能全为空！");
        }

        for (int i = 0; i < ids.length; i++) {
            if(StringUtils.isBlank(ids[i])){
                throw new NullPointerException("id不能为空！");
            }
            Task task = super.selectById(ids[i]);
            dao.deleteById(Integer.parseInt(ids[i]));
            removeTask(task);

        }
        return 0;
    }

    @Override
	public Map<String, String> getAllCron() {
		Map<String, String> maps = new HashMap<String, String>();
		for (Task task : taskList.values()) {
			maps.put(task.getId(), task.getCron());
		}
		return maps;
	}

	@Override
	public List<Task> getAllTask() {
		List<Task> list = new ArrayList<Task>();
		for (Task task : taskList.values()) {
			list.add(task);
		}
		return list;
	}

	@Override
	public Task getTaskById(String taskId) {
		return taskList.get(taskId);
	}

	private Task createScheduleTask(Method m) throws Exception {
		Task task = new Task();
        task.setId("task-" + System.currentTimeMillis());
		Class<?> clazz = m.getDeclaringClass();
		task.setGroupName(clazz.getName());
		task.setTriggerName(clazz.getName() + "." + m.getName());
		if (m.isAnnotationPresent(Scheduled.class)) {
			Annotation sc = m.getAnnotation(Scheduled.class);
			Method cm = sc.getClass().getMethod("cron");
			String cron = cm.invoke(sc).toString();
			task.setCron(cron);
		}
		return task;
	}

	/**
	 * 判断spring容器是否包含该类
	 * 
	 * @param c
	 * @return
	 */
	public boolean ctxContainsBean(Class<?> c) {
		try {
			Object obj = appcontext.getBean(c);
			if (obj != null) {
				return true;
			}
		} catch (NoSuchBeanDefinitionException e) {
			return false;
		}
		return false;
	}

	/**
	 * 判断spring容器是否包含该bean
	 * 
	 * @param name
	 * @return
	 */
	public boolean ctxContainsBean(String name) {
		try {
			Object obj = appcontext.getBean(name);
			if (obj != null) {
				return true;
			}
		} catch (NoSuchBeanDefinitionException e) {
			return false;
		}
		return false;
	}

	@Override
	public Task addTask(Task task) throws Exception {
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		JobDetailImpl jobDetail = new JobDetailImpl();
		jobDetail.setName(task.getId());
		jobDetail.setGroup(task.getGroupName());
		jobDetail.setJobClass(ProxyJob.class);

		TriggerBuilder<Trigger> tig = TriggerBuilder.newTrigger();
		TriggerBuilder<Trigger> tb = tig.withIdentity(task.getTriggerName(), task.getTriggerGrop())
				.withIdentity(task.getName(), task.getTriggerGrop());

		TriggerBuilder<CronTrigger> tsb = tb.withSchedule(CronScheduleBuilder.cronSchedule(task.getCron()));

		CronTrigger trigger = (CronTrigger) tsb.build();

		Class<?> clazz = Class.forName(task.getGroupName());
		// 无缝集成spring
		Object target = null;

		if (!ctxContainsBean(clazz)) {
			target = clazz.newInstance();
		} else {
			target = appcontext.getBean(clazz);
		}

		Method m = clazz.getMethod(task.getTriggerName().replace(task.getGroupName() + ".", ""));
		trigger.getJobDataMap().put(ProxyJob.DATA_TARGET_KEY, target);
		trigger.getJobDataMap().put(ProxyJob.DATA_TRIGGER_KEY, m);
		trigger.getJobDataMap().put(ProxyJob.DATA_TRIGGER_PARAM_KEY, new Object[] {});
		trigger.getJobDataMap().put(ProxyJob.DATA_TASK_KEY, task);

		scheduler.scheduleJob(jobDetail, trigger);

		if (!scheduler.isShutdown()) {
			scheduler.start();
		}
		if (!taskList.containsKey(task.getId())) {
			taskList.put(task.getId(), task);
		}

		return task;
	}


	@Override
	public Task modifyTaskCron(String taskId, String cron) {
		// 获取任务
		Task task = taskList.get(taskId);
		// 停止调
		this.pauseTask(taskId);
		// 修改cron
		task.setCron(cron);
		// 启动
		restartTask(taskId);
		return task;
	}

    @Override
	public Task removeTask(Task task) {

		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			TriggerKey triggerKey = new TriggerKey(task.getId(), task.getTriggerName());
			scheduler.pauseTrigger(triggerKey);
			scheduler.unscheduleJob(triggerKey);
			JobKey jobKey = new JobKey(task.getId(), task.getGroupName());
			scheduler.deleteJob(jobKey);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return task;
	}

	@Override
	public Task restartTask(String taskId) {
		Task task = pauseTask(taskId);
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			if (task != null) {
				TriggerKey triggerKey = new TriggerKey(taskId, task.getTriggerName());
				scheduler.resumeTrigger(triggerKey);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return task;
	}

	@Override
	public Task pauseTask(String taskId) {
		Task task = taskList.get(taskId);
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			TriggerKey triggerKey = new TriggerKey(taskId, task.getTriggerName());
			JobKey jobKey = new JobKey(taskId, task.getGroupName());
			scheduler.pauseJob(jobKey);
			scheduler.pauseTrigger(triggerKey);
			scheduler.unscheduleJob(triggerKey);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return task;
	}

	@Override
	public Task disableTask(String taskId) {
		Task task = taskList.get(taskId);
		try {
			pauseTask(taskId);
			taskList.remove(taskId);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
		return task;
	}

	@Override
	public Task shutdownTask(String taskId) {
		throw new RuntimeException("TaskService.disableTask(String taskId)还没有实现的");
	}

	/**
	 * 创建JobDetail
	 * @return
	 */
	private JobDetail createJobDetail(Task task) {
		JobDetailImpl jobDetail = new JobDetailImpl();
		jobDetail.setName(task.getId());
		jobDetail.setGroup(task.getGroupName());
		jobDetail.setJobClass(ProxyJob.class);
		return jobDetail;
	}

	/**
	 * 创建CronTrigger
	 * @param task
	 * @return
	 */
	private CronTrigger createCronTrigger(Task task) {
		TriggerBuilder<Trigger> tig = TriggerBuilder.newTrigger();
		TriggerBuilder<Trigger> tb = tig.withIdentity(task.getTriggerName(), task.getTriggerGrop())
				.withIdentity(task.getName(), task.getTriggerGrop());
		TriggerBuilder<CronTrigger> tsb = tb.withSchedule(CronScheduleBuilder.cronSchedule(task.getCron()));
		CronTrigger trigger = (CronTrigger) tsb.build();
		return trigger;
	}

	@Override
	public void startAllTask() {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			for (Task task : taskList.values()) {
				JobKey jobKey = new JobKey(task.getId(), task.getGroupName());
				TriggerKey triggerKey = new TriggerKey(task.getId(), task.getGroupName());
				if (!scheduler.checkExists(jobKey) && scheduler.checkExists(triggerKey)) {
					JobDetail jobDetail = createJobDetail(task);
					CronTrigger trigger = createCronTrigger(task);
					scheduler.scheduleJob(jobDetail, trigger);
				}
			}
			if (scheduler.isShutdown()) {
				scheduler.start();
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

	}

	@Override
	public void shutdownAllTask() {
		try {
			Scheduler scheduler = schedulerFactoryBean.getScheduler();
			if (scheduler.isStarted()) {
				scheduler.shutdown(true);
			}
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	@Override
	public void setApplicationContext(ApplicationContext appcontext) throws BeansException {
		this.appcontext = appcontext;
	}
}
